package cn.ddm.hrm.service.impl;



import cn.ddm.hrm.config.HighlightResultMapper;
import cn.ddm.hrm.doc.CourseDoc;
import cn.ddm.hrm.query.CourseDocQuery;
import cn.ddm.hrm.repository.CourseElasticsearchRepository;
import cn.ddm.hrm.service.ICourseDocService;
import cn.ddm.hrm.util.AggsVo;
import cn.ddm.hrm.util.AjaxResult;
import cn.ddm.hrm.util.PageList;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;


import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

@Service
public class CourseDocServiceImpl implements ICourseDocService {

    @Autowired
    private CourseElasticsearchRepository repository;

    @Autowired
    private ElasticsearchTemplate template;

    @Autowired
    private HighlightResultMapper highlightResultMapper;

    @Override
    public AjaxResult batchAdd(List<CourseDoc> courseDocs) {
        repository.saveAll(courseDocs);
        return AjaxResult.me();
    }

    @Override
    public AjaxResult batchDel(List<Long> ids) {
        Iterable<CourseDoc> allById = repository.findAllById(ids);
        repository.deleteAll(allById);
        return AjaxResult.me();
    }
    @Override
    public PageList<CourseDoc> queryPageData(CourseDocQuery query) {
        // 创建构造器
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        // 查询条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        // 得到关键字
        String keyword = query.getKeyword();
        if (!StringUtils.isEmpty(keyword)) {
            queryBuilder.must(QueryBuilders.multiMatchQuery(keyword, "name", "forUser", "courseTypeName", "gradeName", "tenantName"));
        }
        // 过滤
        Long courseTypeId = query.getCourseTypeId();
        if (courseTypeId != null) {
            queryBuilder.filter(QueryBuilders.termQuery("courseTypeId", courseTypeId));
        }
        Long tenantId = query.getTenantId();
        if (tenantId != null) {
            queryBuilder.filter(QueryBuilders.termQuery("tenantId", tenantId));
        }
        // 价格
        Integer priceMax = query.getPriceMax();
        Integer priceMin = query.getPriceMin();
        if (priceMin != null && priceMax != null) {
            queryBuilder.filter(QueryBuilders.rangeQuery("price").gte(priceMin).lte(priceMax));
        }

        builder.withQuery(queryBuilder);

        // 排序
        String sortField = query.getSortField();
        // 默认是价格
        String sortFiledName = "price";
        switch (sortField.toLowerCase()) {
            case "xL": sortFiledName="saleCount";break;
            case "xp": sortFiledName="onlineTime";break;
            case "pl": sortFiledName="commentCount";break;
            case "rq": sortFiledName="viewCount";break;
        }
        // 升降序 默认是降序
        SortOrder desc = SortOrder.DESC;
        if (query.getSortType().equals("desc"))
            desc = SortOrder.ASC;
        builder.withSort(new FieldSortBuilder(sortFiledName).order(desc));

        // 分页
        builder.withPageable(PageRequest.of(query.getPage() - 1, query.getRows()) );

        // 高亮查询
        HighlightBuilder.Field field = new HighlightBuilder.Field("name").preTags("<font style='color:red'><b>").postTags("</b></font>");
        builder.withHighlightFields(field);  // 名字高亮


        // 聚合查询
        builder.addAggregation(AggregationBuilders.terms("tenantNameAgg").field("tenantName.keyword").size(20));
        builder.addAggregation(AggregationBuilders.terms("couseTypeAgg").field("courseTypeName.keyword").size(20));

        // 封装结果
        HashMap<String, List<AggsVo>> map = new HashMap<>();
        AggregatedPage<CourseDoc> page = template.queryForPage(builder.build(), CourseDoc.class, highlightResultMapper);
        StringTerms tenantNameAggs = (StringTerms) page.getAggregation("tenantNameAgg");
        List<AggsVo> tenantNameAgg = getAggsVos(tenantNameAggs);
        map.put("tenantNameAggs",tenantNameAgg);
        StringTerms couseTypeAggs = (StringTerms) page.getAggregation("couseTypeAgg");
        List<AggsVo> couseTypeAgg = getAggsVos(couseTypeAggs);
        map.put("courseTypeNameAggs",couseTypeAgg);
        if (page.getTotalElements()==0)
            return new PageList();
        else {
            PageList<CourseDoc> pageList = new PageList<>(page.getTotalElements(), page.getContent());
            pageList.setAggsVoData(map);
            return pageList;
        }
    }

    /**
     * 得到聚合查询
     * @param aggs
     * @return
     */
    private List<AggsVo> getAggsVos(StringTerms aggs) {
        List<AggsVo> aggsVos = aggs.getBuckets().stream().map(bucket -> {
            AggsVo aggsVo = new AggsVo();
            long count = bucket.getDocCount();
            String key = bucket.getKeyAsString();
            aggsVo.setKey(key);
            aggsVo.setCount(count);
            return aggsVo;
        }).collect(Collectors.toList());
        return aggsVos;
    }
}
